package socket.auction.server;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Timer;

import org.apache.log4j.Logger;

import rmi.analytics.server.AnalyticsInterface;
import rmi.billing.server.BillingServerInterface;
import rmi.billing.server.BillingServerSecure;
import rmi.domain.RegistrySingleton;
import rmi.eventing.types.AuctionEvent;
import rmi.eventing.types.BidEvent;
import rmi.eventing.types.UserEvent;
import rmi.eventing.types.UserEvent.Type;

//Autkionsobjekt
public class Auction {
	public static Logger log = Logger.getLogger(Auction.class);
	private int id=0;
	
	private int duration=0;
	private String description="";
	private User creator=null;
	private User hbidUser = new User("none");
	private double hbid=0.00;
	private String end;
	private AuctionManager man;
	private DecimalFormat f = new DecimalFormat("#0.00"); 
	private Timer timer;
	private long starttime=0;
	private AnalyticsInterface analyticsServ=null;
	private BillingServerSecure  billSecure = null;

	
	
	public Auction(int id,int duration, String description, User creator,String end,AuctionManager man, AnalyticsInterface analyticsServ, BillingServerSecure billSecure){
		this.id = id;
		this.description=description;
		this.duration = duration;
		this.creator = creator;
		this.man = man;
		this.end = end;
		this.analyticsServ= analyticsServ;
		this.billSecure = billSecure;
		this.start();
	
	}
	
	//startet Countown
	public void start() {
		sendAuctionStartedEvent();
		starttime = Calendar.getInstance().getTimeInMillis();
		timer = new Timer();
		timer.schedule(new AuctCollectorTask(man,this), duration*1000);	
	
		
	}
	//Endzeit
	public String getEnd(){
		return end;
	}

	public String getDescription(){
		return description;
	}
	public User getCreator(){
		return this.creator;
	}
	public String getCreatorName(){
		return this.creator.getName();
	}
	//Hoechstes Gebot
	public double getHBit(){
		return this.hbid;
	}
	//Hoechstbietender Objekt
	public User getHBitUser(){
		return this.hbidUser;
	}
	//Hoechstbietender Name
	public String getHBitUserName(){
		return this.hbidUser.getName();
	}
	//Neues Gebot (falls Gebot zu niedrig return false else true
	public boolean bid(double bid, User hbitUser){
		sendBidEvent(hbitUser.getName(), bid);
		if (bid>hbid){
			if (!this.hbidUser.getName().equals("none")){
				sendOverbidEvent(this.hbidUser.getName(),bid);
				String message="!new-bid "+getDescription();
				if (this.hbidUser.isLoggedin()){
					//Sendet Notification an ueberbotenen User
					new Notification(this.hbidUser.getPort(),message,this.hbidUser.getIP());
				}
				else{
					//Falls User nicht eingelogged ist speichert Notification
					//im Notificationpool
					this.hbidUser.addNotifications(message);
				}
			}
			//Uberschreiben der HUser
			this.hbidUser= hbitUser;
			hbid= bid;
			return true;
		}
		//Falls Gebot zu niedrig
		return false;
	}
	public int getId() {
		return id;
	}
	//Fuer Server shutdown alle Auktionen abbrechen
	public void stopAuct(){
		timer.cancel();
		timer.purge();
	}
	//Notification ueber Ende der Auktion
	public void notifyUser(){
		String message="!auction-ended "+hbidUser.getName()+" " +f.format(getHBit())+" "+getDescription();
		if (!this.hbidUser.getName().equals("none")){
			//Notification an Gewinner
			if (this.hbidUser.isLoggedin()){
				new Notification(this.hbidUser.getPort(),message,this.hbidUser.getIP());
			}
			else{
				//Falls User nicht eingelogged ist speichert Notification
				//im Notificationpool
				this.hbidUser.addNotifications(message);
			}
		}
		//Notification an Creator
		if (this.creator.isLoggedin()){
			new Notification(this.creator.getPort(),message,this.creator.getIP());
		}
		else{
			//Falls User nicht eingelogged ist speichert Notification
			//im Notificationpool
			this.creator.addNotifications(message);
		}
	}
	
	//Billing
	
	public void billAuct(){
		 if(!(billSecure==null))
			
		
			try {
				billSecure.billAuction(creator.getName(), Integer.valueOf(id).longValue(), hbid);
			} catch (RemoteException e) {
				log.error("BillingServer is not longer available");
				log.debug("Set BillingServerreference to null");
				billSecure=null;
				
			}
	
	}
	
	//Events
	
	private void sendAuctionStartedEvent(){
		if(!(analyticsServ==null)){
		AuctionEvent ev = new AuctionEvent(id);
		ev.setType(AuctionEvent.Type.AUCTION_STARTED);
		
			try {
				analyticsServ.processEvent(ev);
			} catch (RemoteException e) {
				log.error("AnalyticsServer is not longer available");
				log.debug("Set Analyticsreference to null");
				analyticsServ=null;
			}
		}
		
	}
	public void sendAuctionEndedEvent(){
		if(!(analyticsServ==null)){
			AuctionEvent ev = new AuctionEvent(id);
			ev.setType(AuctionEvent.Type.AUCTION_ENDED);
			ev.setStart(starttime);
			if (!(hbidUser.getName().equals("none"))){
				ev.setsuccess();
			}
			try {
				analyticsServ.processEvent(ev);
			} catch (RemoteException e) {
				log.error("AnalyticsServer is not longer available");
				log.debug("Set Analyticsreference to null");
				analyticsServ=null;
			} 
		}
	}
	
	private void sendBidEvent(String username, double price){
		if(!(analyticsServ==null)){
			BidEvent ev = new BidEvent(username,id, price);
			ev.setType(BidEvent.Type.BID_PLACED);
			
			try {
				analyticsServ.processEvent(ev);
			} catch (RemoteException e) {
				log.error("AnalyticsServer is not longer available");
				log.debug("Set Analyticsreference to null");
				analyticsServ=null;
			} 
		}
	}
	private void sendOverbidEvent(String username, double price){
		if(!(analyticsServ==null)){
			BidEvent ev = new BidEvent(username,id, price);
			ev.setType(BidEvent.Type.BID_OVERBID);
			
			try {
				analyticsServ.processEvent(ev);
			} catch (RemoteException e) {
				log.error("AnalyticsServer is not longer available");
				log.debug("Set Analyticsreference to null");
				analyticsServ=null;
			} 
		}
	}
	public void sendBidWonEvent(){
		if(!(analyticsServ==null)){
			if(!hbidUser.getName().equals("none")){
				
				BidEvent ev = new BidEvent(hbidUser.getName(),id, hbid);
				ev.setType(BidEvent.Type.BID_WON);
				
				try {
					analyticsServ.processEvent(ev);
				} catch (RemoteException e) {
					log.error("AnalyticsServer is not longer available");
					log.debug("Set Analyticsreference to null");
					analyticsServ=null;
				} 
			}
		}
	}

}
